﻿using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Threading;

namespace LogoFX.Localization
{
    public sealed class AssemblyLoaderService
    {
        #region Fields

        private static AssemblyLoaderService s_instance;

        private static readonly object s_sync = new object();

        #endregion

        #region Constructors

        private AssemblyLoaderService()
        {

        }

        #endregion

        #region Public Methods

        public IEnumerable<AssemblyName> GenerateLocalAssemblyCollection(string baseAssemblyFullName)
        {
            if (!File.Exists(baseAssemblyFullName))
            {
                return null;
            }

            string path = Path.GetDirectoryName(baseAssemblyFullName);

            AssemblyName assemblyName = AssemblyName.GetAssemblyName(baseAssemblyFullName);

            List<AssemblyName> result = new List<AssemblyName>();

            string localAssemblyFileName = AssemblyResourceUtility.CreateLocalAssemblyFileName(assemblyName);

            DirectoryInfo directoryInfo = new DirectoryInfo(path);
            DirectoryInfo[] localDirs = directoryInfo.GetDirectories();

            foreach (DirectoryInfo localDir in localDirs)
            {
                try
                {
                    CultureInfo cultureInfo = CultureInfo.GetCultureInfoByIetfLanguageTag(localDir.Name);
                }

                catch (Exception)
                {
                    continue;
                }

                string localAssemblyFullFileName = Path.Combine(localDir.FullName, localAssemblyFileName);
                if (File.Exists(localAssemblyFullFileName))
                {
                    AssemblyName localAssemblyName = AssemblyName.GetAssemblyName(localAssemblyFullFileName);
                    result.Add(localAssemblyName);
                }
            }

            return result;
        }

        public void StartLoadResourceSets(AssemblyName assemblyName, LoadResourceSetsHandler callback)
        {
            ThreadPool.QueueUserWorkItem(LoadResourceSetsAsync, new object[]
                                                                    {
                                                                        assemblyName,
                                                                        callback,
                                                                    });
        }

        #endregion

        #region Public Properties

        public static AssemblyLoaderService Instance
        {
            get
            {
                lock (s_sync)
                {
                    return s_instance ?? (s_instance = new AssemblyLoaderService());
                }
            }
        }

        #endregion

        #region Private Members

        private void LoadResourceSetsAsync(object state)
        {
            object[] args = (object[]) state;

            AssemblyName assemblyName = (AssemblyName) args[0];
            LoadResourceSetsHandler callback = (LoadResourceSetsHandler)args[1];

            AssemblyResourceLoader assemblyResourceLoader = AssemblyResourceLoader.CreateInNewDomain(assemblyName);
            ResourceSetCollection result = assemblyResourceLoader.ExtractResources();
            AssemblyResourceLoader.DestroyDomain(assemblyResourceLoader);

            //Thread.Sleep(2000);

            callback(result);
        }

        #endregion
    }

    public delegate void LoadResourceSetsHandler(ResourceSetCollection resourceSetCollection);
}